﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Globalization;
using System.Text.RegularExpressions;
using Outlook = Microsoft.Office.Interop.Outlook;
using Word = Microsoft.Office.Interop.Word;

namespace MAQEmailGuidelines
{
    class ViolationCheckHelper
    {   
		// This property stores subject of mail
        public string MailSubject { get; set; }
		// This property stores email background 
        public string HTMLMailBody { get; set; }
		// This property stores message of mail
        public string MailBody { get; set; }
		// This property stores recepients in the To field of mail
        public string MailTo { get; set; }
		// This property stores recepients in the BCC field of mail
        public string MailBCC { get; set; }
		// This property stores list of attachments in the mail
        public Outlook.Attachments MailAttachment { get; set; }
        //limits number of error strings to show
        private int numberOfStringsToShow;
        public int NumberOfStringsToShow { get { return numberOfStringsToShow; } set { numberOfStringsToShow = value; } }
        public object MailItem;

		//This constructor initializes the properties. 
        public ViolationCheckHelper(object Item,MailErrors.MailType mailType)
        {            
            if (mailType == MailErrors.MailType.Mail)
            {
                MailItem = Item as Outlook.MailItem;                
                MailTo = ((dynamic)MailItem).To;
                MailBCC = ((dynamic)MailItem).Bcc;
                HTMLMailBody = ((dynamic)MailItem).HTMLBody;
            }
            else
            {
                MailItem = Item as Outlook.MeetingItem;                
                //For Meeting type, we don't check if it's sent to multiple recipients.
                MailTo = "";
                //There is no BCC for this type
                MailBCC = "";                
            }            
            MailAttachment = ((dynamic)MailItem).Attachments;
            MailSubject = ((dynamic)MailItem).Subject;            
            MailBody = ((dynamic)MailItem).Body;            
            MailErrors.ViolationList = new List<string>();
            //current limit for error string set as 10
            NumberOfStringsToShow = 10;
        }
              
        /// <summary>
        /// This function checks for uppercase letters 
        /// </summary>		
        /// <param name="MailBody">Email Body</param>		
        /// <returns>Comma separated uppercase strings</returns>
        public void HasAnyUpperCaseWords()
        {
            try
            {
				//strArr stores mail body to check any upper case word.All strings are separated by " ". Carriage return and  line feed are replaced with " "
                string[] strArr = MailBody.Replace("\r", " ").Replace("\n", " ").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                string[] strArrForSubject = MailSubject.Replace("\r", " ").Replace("\n", " ").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                string upperCaseWords = string.Empty;
                int upperCaseCharLimit = Convert.ToInt16(Properties.Resources.UpperCaseCharLimit), numberOfUpperCaseWords = 0;
                foreach (string str in strArr)
                {
					//This condition checks if the string is an uppercase string in mail body 
					//The first condition checks if the string is an empty string
					//The second condition checks if the string length is greater than a specified length(Here it is 3).Strings shorter than that will be ignored
					//The third condition checks for upper case.
                    if (numberOfUpperCaseWords < NumberOfStringsToShow) {
                        if (!string.IsNullOrEmpty(str) && str.Length > upperCaseCharLimit && str.All(c => char.IsUpper(c)))
                        {
                            upperCaseWords += str + ",";
                            numberOfUpperCaseWords++;
                        }                        
                    }
                    else
                    {
                        upperCaseWords += "...";
                        break;
                    }
                    
                }
				
                foreach (string str in strArrForSubject)
                {
					//This condition checks if the string is an uppercase string in subject
                    if (!string.IsNullOrEmpty(str) && str.Length > upperCaseCharLimit && str.All(c => char.IsUpper(c)))
                    {
                        upperCaseWords += str + ",";
                    }
                }

				//This stores comma separated uppercase strings
                upperCaseWords = upperCaseWords.TrimEnd(',');
				//This condition is used to display all the upper case words
                if (!string.IsNullOrEmpty(upperCaseWords))
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",String.Format(Properties.Resources.ErrUppercase, upperCaseWords)));                                        
                }                
            }
            catch (Exception)
            {                
            }
        }

        /// <summary>
        /// This function checks for exclamation mark 
        /// </summary>		
        /// <param name="MailBody">Email Body</param>		
        /// <param name="mailSubject">Email Subject</param>
        /// <returns>Number of exclamations used as a string</returns>
        public void CheckExclamationMark()
        {
            try
            {
				// This is used to count the number of exclamations in the mail body
                int numberOfExclamation = MailBody.Count(exclamationString => exclamationString == '!');
				// This is used to count the total number of exclamations in the mail 
                numberOfExclamation += MailSubject.Count(exclamationString => exclamationString == '!');
                if (numberOfExclamation > 0)
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",String.Format(Properties.Resources.ErrExclamation, (numberOfExclamation))));                     
                }                
            }
            catch (Exception)
            {                
            }
        }


        /// <summary>
        /// Check email background
        /// </summary>		
        /// <param name="htmlMailBody">HTML email body</param>	
        /// <returns>Message that will be shown in the violation box</returns>
        public void CheckMailBackground()
        {
            try
            {
                HTMLMailBody = HTMLMailBody.Substring(HTMLMailBody.IndexOf("<body"));
                HTMLMailBody = HTMLMailBody.Substring(0, HTMLMailBody.IndexOf(">"));
				//This condition checks if there is any background color applied to the mail
                if (HTMLMailBody.IndexOf("bgcolor") > 0 || HTMLMailBody.IndexOf("background") > 0)
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",Properties.Resources.ErrBgImg));                    
                }                
            }
            catch (Exception)
            {                
            }
        }

        /// <summary>
        /// Check recipients in To section
        /// </summary>		
        /// <param name="mailTo">List of recipients in To section from the email</param>	
        /// <returns>Message that will be shown in the violation box</returns>
        public void CheckToCount()
        {
            try
            {
				//This condition checks the number of recepient in the To field separated by ';' and removed all blank spaces 
                if (MailTo.Trim().Split(';').Length > 1)
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",Properties.Resources.ErrMultipleRecipient));
                }                
            }
            catch (Exception)
            {                
            }
        }

        /// <summary>
        /// Check recipients in BCC section
        /// </summary>		
        /// <param name="mailTo">List of recipients in BCC section from the email</param>	
        /// <returns>Message that will be shown in the violation box</returns>
        public void CheckBCC()
        {
            try
            {
				//This condition checks if there is any BCC recepient 
                if (!string.IsNullOrEmpty(MailBCC))
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",Properties.Resources.ErrBcc));                                        
                }                
            }
            catch (Exception)
            {                
            }
        }

        /// <summary>
        /// Check email importance level
        /// </summary>		
        /// <param name="mailItem">Outlook email item</param>	
        /// <returns>Message that will be shown in the violation box</returns>
        public void CheckMailImportance()
        {
            try
            {                
				//This condition checks if the mail is of high importance level
                if (((dynamic)MailItem).Importance == Convert.ToInt16(Outlook.OlImportance.olImportanceHigh))
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",Properties.Resources.ErrImportance));                                                            
                }                
            }
            catch (Exception)
            {                
            }
        }

        /// <summary>
        /// Check for slangs used in the email
        /// </summary>		
        /// <param name="MailBody">Email body</param>	
        /// <param name="mailSubject">Email subject</param>	
        /// <param name="allAttachments">List of attachments</param>	
        /// <param name="strSlangs">List of slangs from Resource file</param>	
        /// <returns>Message that will be shown in the violation box</returns>
        public void CheckForSlang()
        {
            try
            {
				//It gets a file that contains slangs
                string allSlangs = Properties.Resources.Slangs;
                string slangsFoundInMail = String.Empty;
                int numberOfSlangs = 0;
				//This matches all strings in the mail subject, body and attachment with the strings in the slang file 
                foreach (string slang in allSlangs.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (numberOfSlangs < NumberOfStringsToShow)
                    {
                        if (Regex.IsMatch(MailBody, "\\b" + slang + "\\b", RegexOptions.IgnoreCase) || Regex.IsMatch(MailSubject, "\\b" + slang + "\\b", RegexOptions.IgnoreCase))
                        {
                            slangsFoundInMail += slang + ", ";
                            numberOfSlangs++;
                        }
                        else
                        {
                            foreach (Microsoft.Office.Interop.Outlook.Attachment attachment in MailAttachment)
                            {
                                if (Regex.IsMatch(attachment.FileName, "\\b" + slang + "\\b", RegexOptions.IgnoreCase) || Regex.IsMatch(attachment.DisplayName, "\\b" + slang + "\\b", RegexOptions.IgnoreCase))
                                {
                                    slangsFoundInMail += slang + ", ";
                                    numberOfSlangs++;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        slangsFoundInMail += "...";
                        break;
                    }
                }
                slangsFoundInMail = slangsFoundInMail.Trim().TrimEnd(',');
                if (!string.IsNullOrEmpty(slangsFoundInMail))
                {
                    MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",string.Format(Properties.Resources.ErrSlang, slangsFoundInMail)));                                                                                
                }                
            }
            catch (Exception)
            {                
            }
        }
     
        /// <summary>
        /// Check for spelling mistakes
        /// </summary>		
        /// <param name="mailBody">Email body</param>				
        /// <returns>If spell check was successfully triggered or not</returns>
        public void CheckSpellingMistakes()
        {                                 
            try
            {
                Outlook.Inspector inspector = ((dynamic)MailItem).GetInspector;
                Word.Document doc = inspector.WordEditor;
                doc.CheckSpelling();                
            }
            catch (Exception)
            {
                //TODO: Log Exception                                
                MailErrors.ViolationList.Add(String.Concat(++MailErrors.MailViolationCount,". ",Properties.Resources.ErrAddInError));                                                                                                                    
            }
        }
    }
}
